home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
cplasma
/
cplasma.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-03-31
|
12KB
|
436 lines
{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+}
{$M 64384,0,655360}
Uses VgaGraph, Crt;
Const
RandInit : LongInt = 10;
MaxCol = 190; { Last Color }
MinCol = 1; { First Color }
XMax = 319;
XHalf = XMax shr 1;
YMax = 199;
YHalf = YMax shr 1;
Roughness : Real = 10.0; { Default roughness }
FadeOut : Real = 1.0; { Default fade value }
XAspect = 1.2; { Aspect Ratio }
YAspect = 1.0;
Radii : Integer = 32;
XRadii : Integer = 38;
YRadii : Integer = 32;
Var
ArcSinTab : Array[-90..90] of Real; { -1 to +1 }
ArcCosTab : Array[0..180] of Real; { +1 to -1 }
Aspects : Boolean; { Use Square or Aspect? }
Nat_Plasm : Boolean; { Totally random? }
Centre : Boolean; { Is the center random as well? }
PalDelay : Word;
Procedure PrepPalette;
{ Prepares the first VGA palette (fire like) }
var
b : Byte;
begin
SetRGBPalette( 0, 0, 0, 0 );
For b := 0 to 63 do
SetRGBPalette( b+1, b, 0, 0 );
For b := 1 to 63 do
SetRGBPalette( b+64, 63, b, 0 );
For b := 1 to 63 do
SetRGBPalette( b+127, 63, 63, b );
SetRGBPalette( 191, 63, 0, 63 );
For b := 0 to 190 do
PutPixel( 0, b, b );
end;
Procedure PrepPal;
{ Prepares the second VGA palette. }
var
b : Byte;
begin
For b := 0 to 63 do
SetRGBPalette( b+1, b, 0, 63-b );
For b := 1 to 63 do
SetRGBPalette( b+64, 63-b, b, 0 );
For b := 1 to 63 do
SetRGBPalette( b+127, 0, 63-b, b );
end;
Function ArcSin( sn : Real ) : Integer;
{ Returns the ArcSin of an angle. }
var
i : Integer;
last : Real;
lnum : Integer;
begin
lnum := -90;
last := Abs(sn - ArcSinTab[-90]); { Absolute difference }
For i := -89 to 90 do
If Abs(sn-ArcSinTab[i])<last then
begin
last := Abs(sn-ArcSinTab[i]);
lnum := i;
end;
ArcSin := lnum;
end;
Function ArcCos( sn : Real ) : Integer;
{ Returns the ArcCos of an angle. }
var
i : Integer;
last : Real;
lnum : Integer;
begin
lnum := 0;
last := Abs(sn - ArcCosTab[0]); { Absolute difference }
For i := 1 to 180 do
If Abs(sn-ArcCosTab[i])<last then
begin
last := Abs(sn-ArcCosTab[i]);
lnum := i;
end;
ArcCos := lnum;
end;
Function Tan( x : Real ) : Real;
{ Returns a tangent of an angle. }
begin
Tan := Sin(x)/Cos(x);
end;
Function Radians( Ang : Real ) : Real;
{ Converts degrees into radians. }
begin
Radians := Ang/180*Pi;
end;
Function FindX( Ang, Rad : Real ) : Integer;
{ Polar coordinates to cartesian coordinates. }
var
Tmp : Integer;
Tmp2 : Real;
begin
If Aspects then
FindX := Trunc(Cos(Ang/180*Pi)*Rad*XAspect)
else
FindX := Trunc(Cos(Ang/180*Pi)*Rad);
end;
Function FindY( Ang, Rad : Real ) : Integer;
{ Polar coordinates to cartesian coordinates. }
var
Tmp : Integer;
begin
FindY := Trunc(Sin(Ang/180*Pi)*Rad);
end;
Function RandOf( Relat : Byte; Len : Real ) : Byte;
{ Adds an amount of randomness to Relat, depending on the distance Len. }
var
i : Integer;
begin
i := Relat+Random(Trunc(Roughness*Len))-Trunc(Roughness*Len*0.5)-
Trunc(FadeOut*Len);
If i < 1 then
i := 1
else
If i > 190 then
i := 190;
RandOf := Byte(i);
end;
Function Distance( x1, y1, x2, y2 : Integer ) : Real;
{ Returns the distance between two points. }
begin
Distance := Sqrt( Sqr(x1-x2)+Sqr(y1-y2) );
end;
Function ChordDist( x1, y1, x2, y2 : Integer; Dist : Real ) : Real;
{ Returns the distance between two points on a chord. }
begin
ChordDist := (2*ArcSin( Distance(x1,y1,x2,y2)/(2*Dist) )*Pi*Sqr(Dist))/360;
end;
Procedure LineOut( x1, y1, x2, y2 : Integer );
{ Creates the initial line axis of the circular plasma. }
Const
Sqrt2 = 1.4142135624;
var
x3, y3 : Integer;
begin
x3 := (x1+x2) div 2; y3 := (y1+y2) div 2;
If ((x3<>x1) AND (x3<>x2)) OR ((y3<>y1) AND (y3<>y2)) then
begin
PutPixel( x3, y3, RandOf( (GetPixel(x1,y1)+GetPixel(x2,y2))div 2,
Distance( x1, y1, x3, y3 ) ) );
LineOut( x1, y1, x3, y3 );
LineOut( x3, y3, x2, y2 );
end;
end;
Var
WorryAng : Real; { Minimum angle that we have to worry about. }
Quit : Boolean; { Quitin' time. }
Function NearIn( Angle, Radii : Real ) : Byte;
{ Finds out what the nearest pixel at the same angle is equal to. }
var
x, y, i : Integer;
r, Len : Real;
begin
r := Radii;
Repeat
x := FindX( Angle, r ); y := FindY( Angle, r );
r := r - Sqrt(2);
Until GetPixel(x+XHalf,y+YHalf) > 0;
Len := Distance( FindX(Angle,Radii), FindY(Angle,Radii), x, y );
Repeat
i := GetPixel(x+XHalf,y+YHalf)+
Random(Trunc(Roughness*Len))-Trunc(Roughness*Len*0.5);
{ Trunc(FadeOut*Len);}
Until (i < 191) AND (i > 0);
NearIn := Byte(i);
end;
Procedure RoundOut( Ang1, Ang2, Rad : Real );
{ Interpolates what (Ang1+Ang2)/2, Rad is equal to. }
var
Ang3 : Real;
begin
If (Abs(Ang1-Ang2) > WorryAng) AND not Quit then
begin
Ang3 := (Ang1+Ang2)/2;
If GetPixel( FindX( Ang3, Rad )+XHalf, FindY( Ang3, Rad )+YHalf ) = 0 then
begin
{ PutPixel( FindX(Ang3,Rad)+XHalf,FindY(Ang3,Rad)+YHalf, 191 );
Delay( 10 );
PutPixel( FindX(Ang3,Rad)+XHalf,FindY(Ang3,Rad)+YHalf, 0 );}
PutPixel( FindX(Ang3,Rad)+XHalf,FindY(Ang3,Rad)+YHalf,
((Integer(RandOf((GetPixel(FindX(Ang1,Rad)+XHalf,
FindY(Ang1,Rad)+YHalf)+GetPixel(FindX(Ang2,Rad)+XHalf,
FindY(Ang2,Rad)+YHalf)) shr 1,{Chord}Distance(FindX(Ang1,Rad),
FindY(Ang1,Rad),FindX(Ang3,Rad),
FindY(Ang3,Rad){,Rad}))) shl 1)+NearIn( Ang3, Rad )) div 3 );
end;
Quit := KeyPressed;
RoundOut( Ang1, Ang3, Rad );
RoundOut( Ang3, Ang2, Rad );
end;
end;
Procedure Naturalness;
{ Creates a random-based axis. }
begin
If Centre then
PutPixel( XHalf, YHalf, Random(190)+1 )
else
PutPixel( XHalf, YHalf, 190 );
PutPixel( XHalf+XRadii, YHalf, Random(190)+1-Trunc(Radii*FadeOut) );
PutPixel( XHalf-XRadii, YHalf, Random(190)+1-Trunc(Radii*FadeOut) );
PutPixel( XHalf, YHalf+YRadii, Random(190)+1-Trunc(Radii*FadeOut) );
PutPixel( XHalf, YHalf-YRadii, Random(190)+1-Trunc(Radii*FadeOut) );
end;
Procedure RotatePal;
{ Controls the various palette rotations }
type
rgbrec = record r, g, b : Byte; end;
var
Pals : Array[0..255] of RgbRec;
Tmp : RgbRec;
i, j : Integer;
begin
For i := 0 to 255 do
GetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Pals[1].r := 0; Pals[1].g := 0; Pals[1].b := 0;
For i := 1 to 190 do
SetRGBPalette( i, 0, 0, 0 ); { Blank out palette. }
Repeat { Black, rotate in color, rotate out color, black. }
For i := 1 to 190 do { Rotate in color }
begin
For j := 1 to i do
SetRGBPalette( 190-i+j, Pals[j].r, Pals[j].g, Pals[j].b );
Delay( PalDelay );
end;
For i := 2 to 190 do { Rotate through color }
begin
For j := i to 190 do
SetRGBPalette( j-i+1, Pals[j-i+1].r, Pals[j-i+1].g, Pals[j-i+1].b );
SetRGBPalette( 192-i, 0, 0, 0 );
Delay( PalDelay );
end;
For i := 1 to 190 do { Black }
SetRGBPalette( i, 0, 0, 0 );
Until UpCase(ReadKey) in ['Q',#27]; { Until the ESC or Q key. }
Repeat { Rotate colors one way... }
Tmp := Pals[1];
Move( Pals[2], Pals[1], 189*3 );
Pals[190] := Tmp;
For i := 1 to 190 do
SetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Delay( PalDelay );
Until KeyPressed;
ReadKey;
Repeat { Rotate colors the other way... }
Tmp := Pals[190];
Move( Pals[1], Pals[2], 189*3 );
Pals[1] := Tmp;
For i := 1 to 190 do
SetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Delay( PalDelay );
Until KeyPressed;
ReadKey;
PrepPal; { A new palette to play with. }
For i := 0 to 255 do
GetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Repeat { Forward through the colors. }
Tmp := Pals[1];
Move( Pals[2], Pals[1], 189*3 );
Pals[190] := Tmp;
For i := 1 to 190 do
SetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Delay( PalDelay );
Until KeyPressed;
ReadKey;
Repeat { Backward through the colors. }
Tmp := Pals[190];
Move( Pals[1], Pals[2], 189*3 );
Pals[1] := Tmp;
For i := 1 to 190 do
SetRGBPalette( i, Pals[i].r, Pals[i].g, Pals[i].b );
Delay( PalDelay );
Until KeyPressed;
ReadKey;
ReadKey;
end;
Procedure Main;
var
i : Real;
s : Real;
j : Integer;
begin
InitGraph;
PrepPalette;
SetColor( 191 );
Line( XHalf+XRadii+1, YHalf+YRadii+1, xHalf+XRadii+1, YHalf-YRadii-1 );
Line( XHalf+XRadii+1, YHalf+YRadii+1, xHalf-XRadii-1, YHalf+YRadii+1 );
Line( XHalf-XRadii-1, YHalf-YRadii-1, xHalf+XRadii+1, YHalf-YRadii-1 );
Line( XHalf-XRadii-1, YHalf-YRadii-1, xHalf-XRadii-1, YHalf+YRadii+1 );
PutPixel( XHalf, YHalf, 190 );
If Nat_Plasm then
Naturalness;
LineOut( XHalf, YHalf, XHalf+XRadii, YHalf ); { Create plasma axis. }
LineOut( XHalf, YHalf, XHalf-XRadii, YHalf );
LineOut( XHalf, YHalf, XHalf, YHalf+YRadii );
LineOut( XHalf, YHalf, XHalf, YHalf-YRadii );
s := 0.707106781; { Minimum radius to worry about. }
Quit := FALSE;
i := s;
Repeat
RoundOut( 0, 90, i ); { Figgle out plasma from x to y degrees, }
RoundOut( 90, 180, i ); { at radius i }
RoundOut( 180, 270, i );
RoundOut( 270, 360, i );
i := i + s { Radius increases. }
Until i >= Radii;
Write(#7); { Beep! }
ReadKey;
SetRGBPalette( 0, 0, 0, 63 ); { Show any "missed" spots. }
Delay( 1000 );
SetRGBPalette( 0, 0, 0, 0 );
RotatePal;
CloseGraph;
end;
Procedure ReadInput;
var
s : String;
i, e : Integer;
r : Real;
c : Char;
begin
Writeln;
Write( 'Enter # for RandSeed, or nothing for random: ' );
Readln( s );
Val( s, i, e );
If (s='') OR (e<>0) then
Randomize
else
Randseed := i;
Write( 'Roughness value [10.0]: ' );
Readln( s );
Val( s, r, e );
If (s<>'') AND (e=0) then
Roughness := r;
Write( 'Radii (in pixels) [32]: ' );
Readln( s );
Val( s, i, e );
If (s<>'') AND (e=0) then
Radii := i
else
Radii := 32;
If Radii > 100 then
Radii := 100;
Write( 'Fadeout Value [0.0]: ' );
Readln( s );
Val( s, r, e );
If (s<>'') AND (e=0) then
FadeOut := r
else
FadeOut := 0.0;
Write( 'Ejection Angle [0.6]: ' );
Readln( s );
Val( s, r, e );
If (s<>'') AND (e=0) AND (r > 0) then
WorryAng := r
else
WorryAng := 0.6;
Write( 'Delay in palette rotation (ms) [5]: ' );
Readln( s );
Val( s, i, e );
If (s<>'') AND (e=0) then
PalDelay := Abs(i)
else
PalDelay := 5;
Write( 'Correct the screen aspect? <Y/N>' );
Repeat
C := UpCase( ReadKey );
Until C in ['Y','N'];
Aspects := C = 'Y';
If Aspects then
begin
XRadii := Trunc(1.2*Radii);
YRadii := Radii;
end
else
begin
XRadii := Radii;
YRadii := Radii;
end;
Write( #13, #10, 'Use random colors for the endpoints? <Y/N>' );
Repeat
C := UpCase( ReadKey );
Until C in ['Y','N'];
Nat_Plasm := C = 'Y';
If Nat_Plasm then
begin
Write( #13, #10, 'Use a random color for the center? <Y/N>' );
Repeat
C := UpCase( ReadKey );
Until C in ['Y','N'];
Centre := C = 'Y';
end;
end;
Begin
ReadInput;
Main;
End.